home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
236_01
/
bawkact.c
< prev
next >
Wrap
Text File
|
1989-06-05
|
9KB
|
455 lines
/*
HEADER: CUG236;
TITLE: BAWK Actions Compiler;
DATE: 05/17/1987;
VERSION: 1.1;
FILENAME: BAWKACT.C;
SEE-ALSO: BAWK.C;
AUTHORS: W. C. Colley III, B. Brodt;
*/
/*
* Bawk C actions compiler
*/
#include <stdio.h>
#include "bawk.h"
/* Functions local to this module. */
char *str_compile();
int stmt_compile();
int act_compile( actbuf )
char *actbuf; /* where tokenized actions are compiled into */
{
Where = ACTION;
return stmt_compile( actbuf );
}
int pat_compile( actbuf )
char *actbuf; /* where tokenized actions are compiled into */
{
Where = PATTERN;
return stmt_compile( actbuf );
}
int stmt_compile( actbuf )
char *actbuf; /* where tokenized actions are compiled into */
{
/*
* Read and tokenize C actions from current input file into the
* action buffer. Strip out comments and whitespace in the
* process.
*/
char *actptr, /* actbuf pointer */
*cp, /* work pointer */
buf[MAXLINELEN];/* string buffer */
int braces, /* counts '{}' pairs - return when 0 */
parens, /* counts '()' pairs */
i, /* temp */
c; /* current input character */
braces = parens = 0;
actptr = actbuf;
while ( (c = getcharacter()) != -1 )
{
/*
* Skip over spaces, tabs and newlines
*/
if ( c==' ' || c=='\t' || c=='\n' )
continue;
if ( c=='#' )
{
/*
* Skip comments. Comments start with a '#' and
* end at the next newline.
*/
while ( (c = getcharacter()) != -1 && c!='\n' )
;
continue;
}
if ( c=='{' )
{
if ( Where==PATTERN )
{
/*
* We're compiling a pattern. The '{' marks
* the beginning of an action statement.
* Push the character back and return.
*/
ungetcharacter( '{' );
break;
}
else
{
/*
* We must be compiling an action statement.
* '{'s mark beginning of action or compound
* statements.
*/
++braces;
*actptr++ = T_LBRACE;
}
}
else if ( c=='}' )
{
*actptr++ = T_RBRACE;
if ( ! --braces )
/*
* Found the end of the action string
*/
break;
}
else if ( c=='(' )
{
++parens;
*actptr++ = T_LPAREN;
}
else if ( c==')' )
{
if ( --parens < 0 )
error( "mismatched '()'", ACT_ERROR );
*actptr++ = T_RPAREN;
}
else if ( c==',' && !braces && !parens && Where==PATTERN )
{
/*
* found a comma outside of any braces or parens-
* this must be a regular expression seperator.
*/
ungetcharacter( ',' );
break;
}
/*
* Check if it's a regular expression:
*/
else if ( c=='/' )
{
/*
* A '/' inside a pattern string starts a regular
* expression. Inside action strings, a '/' is
* the division operator.
*/
if ( Where == PATTERN )
goto dopattern;
else
*actptr++ = T_DIV;
}
else if ( c=='@' )
{
dopattern:
/*
* Within action strings, only the '@' may be used to
* delimit regular expressions
*/
*actptr++ = T_REGEXP;
ungetcharacter( c );
actptr += re_compile( actptr );
}
/*
* symbol, string or constant:
*/
else if ( alpha( c ) )
{
/*
* It's a symbol reference. Copy the symbol into
* string buffer.
*/
cp = buf;
do
*cp++ = c;
while ( (c=getcharacter()) != -1 && alphanum( c ) );
ungetcharacter( c );
*cp = 0;
/*
* Check if a keyword, builtin function or variable.
*/
if ( c = iskeyword( buf ) )
*actptr++ = c;
else if ( i = isfunction( buf ) )
{
*actptr++ = T_FUNCTION;
#if MPU68000 || MC68000
if ( (long) actptr & 0x1) actptr++;
#endif
*((int *)actptr) = i;
actptr += sizeof (int *);
}
else
{
/*
* It's a symbol name.
*/
*actptr++ = T_VARIABLE;
if (!(cp = (char *)findvar(buf)))
cp = (char *)addvar(buf);
#if MPU68000 || MC68000
if ( (long) actptr & 0x1) actptr++;
#endif
*((char **)actptr) = cp;
actptr += sizeof (char **);
}
}
else if ( c == '"' )
{
/*
* It's a string constant
*/
*actptr++ = T_STRING;
actptr = str_compile( actptr, '"' );
}
else if ( c == '\'' )
{
/*
* It's a character constant
*/
*actptr++ = T_CONSTANT;
str_compile( buf, '\'' );
#if MPU68000 || MC68000
if ( (long) actptr & 0x1) actptr++;
#endif
*((int *)actptr) = *buf;
actptr += sizeof (int *);
}
else if (isdigit(c))
{
/*
* It's a numeric constant
*/
*actptr++ = T_CONSTANT;
cp = buf;
do
*cp++ = c;
while ((c=getcharacter()) != -1 && isdigit(c));
ungetcharacter( c );
*cp = 0;
#if MPU68000 || MC68000
if ( (long) actptr & 0x1) actptr++;
#endif
*((int *)actptr) = atoi(buf);
actptr += sizeof (int *);
}
/*
* unary operator:
*/
else if ( c == '$' )
*actptr++ = T_DOLLAR;
/*
* or binary operator:
*/
else if ( c == '=' )
{
if ( (c=getcharacter()) == '=' )
*actptr++ = T_EQ;
else
{
ungetcharacter( c );
*actptr++ = T_ASSIGN;
}
}
else if ( c == '!' )
{
if ( (c=getcharacter()) == '=' )
*actptr++ = T_NE;
else
{
ungetcharacter( c );
*actptr++ = T_LNOT;
}
}
else if ( c == '<' )
{
if ( (c=getcharacter()) == '<' )
*actptr++ = T_SHL;
else if ( c == '=' )
*actptr++ = T_LE;
else
{
ungetcharacter( c );
*actptr++ = T_LT;
}
}
else if ( c == '>' )
{
if ( (c=getcharacter()) == '>' )
*actptr++ = T_SHR;
else if ( c == '=' )
*actptr++ = T_GE;
else
{
ungetcharacter( c );
*actptr++ = T_GT;
}
}
else if ( c == '&' )
{
if ( (c=getcharacter()) == '&' )
*actptr++ = T_LAND;
else
{
ungetcharacter( c );
*actptr++ = T_AND;
}
}
else if ( c == '|' )
{
if ( (c=getcharacter()) == '|' )
*actptr++ = T_LIOR;
else
{
ungetcharacter( c );
*actptr++ = T_IOR;
}
}
else if ( c == '+' )
{
if ( (c=getcharacter()) == '+' )
*actptr++ = T_INCR;
else
{
ungetcharacter( c );
*actptr++ = T_ADD;
}
}
else if ( c == '-' )
{
if ( (c=getcharacter()) == '-' )
*actptr++ = T_DECR;
else
{
ungetcharacter( c );
*actptr++ = T_SUB;
}
}
/*
* punctuation
*/
else if ( instr( c, "[](),;*/%+-^~" ) )
*actptr++ = c;
else
{
/*
* Bad character in input line
*/
error( "lexical error", ACT_ERROR );
}
if ( actptr >= Workbuf + MAXWORKBUFLEN )
error( "action too long", MEM_ERROR );
}
if ( braces || parens )
error( "mismatched '{}' or '()'", ACT_ERROR );
*actptr++ = T_EOF;
return actptr - actbuf;
}
char *str_compile( str, delim )
char *str, delim;
{
/*
* Compile a string from current input file into the given string
* buffer. Stop when input character is the delimiter in "delim".
* Returns a pointer to the first character after the string.
*/
int c;
char buf[ MAXLINELEN ];
while ( (c = getcharacter()) != -1 && c != delim)
{
if ( c == '\\' )
{
switch ( c = getcharacter() )
{
case -1: goto err;
case 'b': c = '\b'; break;
case 'n': c = '\n'; break;
case 't': c = '\t'; break;
case 'f': c = '\f'; break;
case 'r': c = '\r'; break;
case '0':
case '1':
case '2':
case '3':
*buf = c;
for ( c=1; c<3; ++c )
{
if ( (buf[c]=getcharacter()) == -1 )
goto err;
}
buf[c] = 0;
sscanf( buf, "%o", &c );
break;
case '\n':
if ( getcharacter() == -1 )
goto err;
default:
if ( (c = getcharacter()) == -1 )
goto err;
}
}
*str++ = c;
}
*str++ = 0;
return str;
err:
sprintf( buf, "missing %c delimiter", delim );
error( buf, 4 );
}
int getoken()
{
switch ( Token = *Actptr++ )
{
case T_STRING:
case T_REGEXP:
Value.dptr = Actptr;
Actptr += strlen( Actptr ) + 1;
break;
case T_VARIABLE:
#if MPU68000 || MC68000
if (